package han.yang.service.group.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import han.yang.common.ResponseVO;
import han.yang.common.enums.GroupErrorCode;
import han.yang.common.enums.GroupMemberRoleEnum;
import han.yang.common.enums.GroupStatusEnum;
import han.yang.common.enums.GroupTypeEnum;
import han.yang.common.exception.ApplicationException;
import han.yang.service.group.dao.ImGroupEntity;
import han.yang.service.group.dao.ImGroupMemberEntity;
import han.yang.service.group.dao.mapper.ImGroupMapper;
import han.yang.service.group.model.dto.GroupMemberDto;
import han.yang.service.group.model.req.*;
import han.yang.service.group.model.resp.GetGroupResp;
import han.yang.service.group.model.resp.GetRoleInGroupResp;
import han.yang.service.group.service.ImGroupMemberService;
import han.yang.service.group.service.ImGroupService;
import han.yang.service.user.dao.ImUserDataEntity;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ImGroupServiceImpl implements ImGroupService {
    @Resource
    ImGroupMapper imGroupMapper;

    @Resource
    ImGroupMemberService imGroupMemberService;

    @Override
    public ResponseVO<?> importGroup(ImportGroupReq req) {
        // 判断是否有群id，没有则系统分配
        if (StringUtils.isNotBlank(req.getGroupId())) {
            // 判断群是否存在
            QueryWrapper<ImGroupEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("app_id", req.getAppId());
            queryWrapper.eq("group_id", req.getGroupId());
            if (imGroupMapper.selectCount(queryWrapper) > 0) {
                // 记录已经存在
                return ResponseVO.errorResponse(GroupErrorCode.GROUP_IS_EXIST);
            }
        } else {
            req.setGroupId(UUID.randomUUID().toString().replace("-", ""));
        }
        // 插入info
        ImGroupEntity imGroupEntity = new ImGroupEntity();
        imGroupEntity.setGroupId(req.getGroupId());
        imGroupEntity.setGroupName(req.getGroupName());
        imGroupEntity.setGroupType(req.getGroupType());
        imGroupEntity.setOwnerId(req.getOwnerId());
        imGroupEntity.setAppId(req.getAppId());
        imGroupEntity.setMute(req.getMute());
        imGroupEntity.setApplyJoinType(req.getApplyJoinType());
        imGroupEntity.setIntroduction(req.getIntroduction());
        imGroupEntity.setNotification(req.getNotification());
        imGroupEntity.setPhoto(req.getPhoto());
        imGroupEntity.setMaxMemberCount(req.getMaxMemberCount());
        imGroupEntity.setCreateTime(req.getCreateTime() != null ?
                req.getCreateTime() : System.currentTimeMillis());
        imGroupEntity.setExtra(req.getExtra());
        try {
            int insert = imGroupMapper.insert(imGroupEntity);
            if (insert == 1) {
                return ResponseVO.successResponse();
            } else {
                return ResponseVO.errorResponse(GroupErrorCode.IMPORT_GROUP_ERROR);
            }
        } catch (Exception e) {
            throw new ApplicationException(GroupErrorCode.IMPORT_GROUP_ERROR);
        }
    }

    @Override
    public ResponseVO<ImGroupEntity> getGroup(String groupId, Integer appId) {
        QueryWrapper<ImGroupEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("app_id", appId);
        queryWrapper.eq("group_id", groupId);
        queryWrapper.eq("status", 0);
        try {
            ImGroupEntity entity = imGroupMapper.selectOne(queryWrapper);
            if (entity == null) {
                return ResponseVO.errorResponse(GroupErrorCode.GROUP_IS_NOT_EXIST);
            } else {
                return ResponseVO.successResponse(entity);
            }
        } catch (Exception e) {
            throw new ApplicationException(GroupErrorCode.GET_INFO_ERROR);
        }
    }

    @Override
    public ResponseVO<?> updateGroupInfo(UpdateGroupReq req) {
        ResponseVO<ImGroupEntity> group = getGroup(req.getGroupId(), req.getAppId());
        if (!group.isOk()) {
            return group;
        }
        boolean isAdmin = false;
        if (!isAdmin) {
            // 不是管理员则需要校验权限
            ResponseVO<GetRoleInGroupResp> role = imGroupMemberService.getRoleInGroupOne(req.getGroupId(), req.getOperater(), req.getAppId());
            if (!role.isOk()) {
                return role;
            }
            GetRoleInGroupResp roleData = role.getData();
            // 是否为管理员
            boolean isManager = roleData.getRole() == GroupMemberRoleEnum.MAMAGER.getCode();
            // 是否为群主
            boolean isOwner = roleData.getRole() == GroupMemberRoleEnum.OWNER.getCode();
            // 判断是否为公开群
            if (GroupTypeEnum.PUBLIC.getCode() == group.getData().getGroupType()) {
                // 只有群主和管理员修改
                if (!isManager && !isOwner) {
                    return ResponseVO.errorResponse(GroupErrorCode.THIS_OPERATE_NEED_MANAGER_ROLE);
                }
            }
        }
        ImGroupEntity entity = new ImGroupEntity();
        entity.setGroupId(req.getGroupId());
        if (StringUtils.isNotBlank(req.getGroupName()))
            entity.setGroupName(req.getGroupName());
        entity.setApplyJoinType(req.getApplyJoinType());
        if (StringUtils.isNotBlank(req.getIntroduction()))
            entity.setIntroduction(req.getIntroduction());
        if (StringUtils.isNotBlank(req.getExtra()))
            entity.setExtra(req.getExtra());
        if (StringUtils.isNotBlank(req.getNotification()))
            entity.setNotification(req.getNotification());
        if (StringUtils.isNotBlank(req.getPhoto()))
            entity.setPhoto(req.getPhoto());
        entity.setMaxMemberCount(req.getMaxMemberCount());
        entity.setMute(req.getMute());
        int update = imGroupMapper.update(entity, new QueryWrapper<ImGroupEntity>()
                .eq("group_id", req.getGroupId())
                .eq("app_id", req.getAppId()));
        if (update != 1) {
            throw new ApplicationException(GroupErrorCode.UPDATE_GROUP_BASE_INFO_ERROR);
        } else {
            return ResponseVO.successResponse();
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResponseVO<?> createGroup(CreateGroupReq req) {
        boolean isAdmin = false;
        if (!isAdmin) {
            req.setOwnerId(req.getOperater());
        }
        QueryWrapper<ImGroupEntity> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isBlank(req.getGroupId())) {
            // 分配groupid
            req.setGroupId(UUID.randomUUID().toString().replace("-", ""));
        } else {
            queryWrapper.eq("group_id", req.getGroupId());
            queryWrapper.eq("app_id", req.getAppId());
            Integer integer = imGroupMapper.selectCount(queryWrapper);
            if (integer > 0) {
                throw new ApplicationException(GroupErrorCode.GROUP_IS_EXIST);
            }
        }
        if (req.getGroupType() == GroupTypeEnum.PUBLIC.getCode() && StringUtils.isBlank(req.getOwnerId())) {
            throw new ApplicationException(GroupErrorCode.PUBLIC_GROUP_MUST_HAVE_OWNER);
        }
        try {
            // 创建群
            ImGroupEntity entity = new ImGroupEntity();
            entity.setCreateTime(System.currentTimeMillis());
            entity.setStatus(GroupStatusEnum.NORMAL.getCode());
            BeanUtils.copyProperties(req, entity);
            int insert = imGroupMapper.insert(entity);
            // 插入群主信息
            GroupMemberDto groupMemberDto = new GroupMemberDto();
            groupMemberDto.setMemberId(req.getOwnerId());
            groupMemberDto.setRole(GroupMemberRoleEnum.OWNER.getCode());
            groupMemberDto.setJoinTime(System.currentTimeMillis());
            imGroupMemberService.addGroupMember(req.getGroupId(), req.getAppId(), groupMemberDto);
        } catch (Exception e) {
            // 群的创建和群主的记录必须在一个事务里面
            throw new ApplicationException(GroupErrorCode.CREATE_GROUP_ERROR);
        }
        List<String> success = new ArrayList<>();
        List<String> error = new ArrayList<>();
        //  插入携带的群成员信息
        if (req.getMember() != null && req.getMember().size() > 1) {
            // TODO 后续改为批量插入
            req.getMember().forEach(dto -> {
                ResponseVO resp = null;
                try {
                    resp = imGroupMemberService.addGroupMember(req.getGroupId(), req.getAppId(), dto);
                } catch (Exception e) {
                    // 成员的导入不影响群的创建，所以不需要将异常抛出
                    error.add(dto.getMemberId());
                }
                if (resp.isOk()) {
                    success.add(dto.getMemberId());
                } else {
                    error.add(dto.getMemberId());
                }
            });
        }
        HashMap<String, List> importMemberStatus = new HashMap<>();
        importMemberStatus.put("success", success);
        importMemberStatus.put("error", error);
        return ResponseVO.successResponse(importMemberStatus);
    }

    @Override
    public ResponseVO getGroupInfo(GetGroupReq req) {
        ResponseVO group = this.getGroup(req.getGroupId(), req.getAppId());
        if(!group.isOk()){
            return group;
        }
        GetGroupResp getGroupResp = new GetGroupResp();
        BeanUtils.copyProperties(group.getData(), getGroupResp);
        try {
            ResponseVO<List<GroupMemberDto>> groupMember = imGroupMemberService.getGroupMember(req.getGroupId(), req.getAppId());
            if (groupMember.isOk()){
                getGroupResp.setMemberList(groupMember.getData());
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return ResponseVO.successResponse(getGroupResp);
    }

    @Override
    public ResponseVO getJoinedGroup(GetJoinedGroupReq req) {
        // 根据memberId获取所有加入的群id
        ResponseVO<Collection<String>> memberJoinedGroup = imGroupMemberService.getMemberJoinedGroup(req);
        if (memberJoinedGroup.isOk()){
            Collection<String> data = memberJoinedGroup.getData();
            QueryWrapper<ImGroupEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("app_id",req.getAppId());
            if (!CollectionUtils.isEmpty(req.getGroupType()))
                queryWrapper.in("group_type",req.getGroupType());
            queryWrapper.in("group_id",data);
            List<ImGroupEntity> res = imGroupMapper.selectList(queryWrapper);
            return ResponseVO.successResponse(res);
        }else {
            return ResponseVO.errorResponse(GroupErrorCode.GET_INFO_ERROR);
        }
    }

    /**
     * 私有群只支持app管理员解散、公有群支持后台管理员和群主解散
     * @param req 请求
     * @return
     */
    @Override
    public ResponseVO destroyGroup(DestroyGroupReq req) {
        boolean isAdmin = false;
        QueryWrapper<ImGroupEntity> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.eq("group_id", req.getGroupId());
        objectQueryWrapper.eq("app_id", req.getAppId());
        ImGroupEntity imGroupEntity = imGroupMapper.selectOne(objectQueryWrapper);
        if (imGroupEntity == null) {
            // 群聊不存在
            throw new ApplicationException(GroupErrorCode.GROUP_IS_NOT_EXIST);
        }
        if (imGroupEntity.getStatus() == GroupStatusEnum.DESTROY.getCode()){
            // 群聊已经被删除
            throw new ApplicationException(GroupErrorCode.GROUP_IS_DESTROY);
        }
        if (imGroupEntity.getGroupType() == GroupTypeEnum.PRIVATE.getCode()){
            // 群聊为私有群，不能够被删除
            throw new ApplicationException(GroupErrorCode.PRIVATE_GROUP_CAN_NOT_DESTORY);
        }
        if (isAdmin){
            if (!imGroupEntity.getOwnerId().equals(req.getOperater())) {
                // 不是群主不能删除
                throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_OWNER_ROLE);
            }
        }
        imGroupEntity.setStatus(GroupStatusEnum.DESTROY.getCode());
        int update = imGroupMapper.update(imGroupEntity, objectQueryWrapper);
        if (update != 1) {
            throw new ApplicationException(GroupErrorCode.UPDATE_GROUP_BASE_INFO_ERROR);
        }
        return ResponseVO.successResponse();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResponseVO transferGroup(TransferGroupReq req) {
        // 查询群信息
        QueryWrapper<ImGroupEntity> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.eq("group_id", req.getGroupId());
        objectQueryWrapper.eq("app_id", req.getAppId());
        ImGroupEntity imGroupEntity = imGroupMapper.selectOne(objectQueryWrapper);
        if(imGroupEntity.getStatus() == GroupStatusEnum.DESTROY.getCode()){
            throw new ApplicationException(GroupErrorCode.GROUP_IS_DESTROY);
        }
        // 查询操作人在群内部的职位
        ResponseVO<GetRoleInGroupResp> role = imGroupMemberService
                .getRoleInGroupOne(req.getGroupId(),req.getOperater(),req.getAppId());
        if (!role.isOk()) {
            return role;
        }
        if (role.getData().getRole() != GroupMemberRoleEnum.OWNER.getCode()) {
            return ResponseVO.errorResponse(GroupErrorCode.THIS_OPERATE_NEED_OWNER_ROLE);
        }
        // 查询被转让人是否在群内部
        ResponseVO<GetRoleInGroupResp> newOwnerRole = imGroupMemberService
                .getRoleInGroupOne(req.getGroupId(), req.getOwnerId(), req.getAppId());
        if (!newOwnerRole.isOk()) {
            return newOwnerRole;
        }
        imGroupEntity.setOwnerId(req.getOwnerId());
        int update = imGroupMapper.update(imGroupEntity, objectQueryWrapper);
        if (update != 1) {
            throw new ApplicationException(GroupErrorCode.UPDATE_GROUP_BASE_INFO_ERROR);
        }
        imGroupMemberService.transferGroupMember(req.getOwnerId(), req.getGroupId(), req.getAppId());
        return ResponseVO.successResponse();
    }

}